[sw] Pull-in MLDSA software impl for eg100#30552
Conversation
a394044 to
720ee09
Compare
| register uint8_t *a0 asm("a0") = out_pk; | ||
| register const uint8_t *a1 asm("a1") = seed; | ||
| register void *a2 asm("a2") = stack_top; | ||
|
|
||
| asm volatile( | ||
| "mv s1, sp\n" | ||
| "mv sp, a2\n" | ||
| "call mldsa44_tiny_pub_from_seed\n" | ||
| "mv sp, s1\n" | ||
| : "+r"(a0), "+r"(a1), "+r"(a2) | ||
| : | ||
| : "ra", "s1", "a3", "a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3", "t4", | ||
| "t5", "t6", "memory"); |
There was a problem hiding this comment.
This is pretty advanced stuff :)
What does the codegen look like for this, and how does this compare with writing an actual assembly language entrypoint (e.g. mldsa44_tiny_caller.S)?
With an assembly-language entrypoint, we could simply obey the C-ABI register convention rather than having to mark it all as clobbered in the inline assembly statement. However, we'd have to appropriately manage whichever register is responsible for holding the original stack pointer so we can restore it after the call returns.
There was a problem hiding this comment.
(Hmm, I forgot the reason why I decided to switch from standalone asm to inline asm during prototyping...)
The PR is updated to use assembly-language entrypoint, and I also confirmed manually that unused functions will be stripped correctly.
| cc_library( | ||
| name = "mldsa44", | ||
| srcs = ["mldsa44.c"], | ||
| hdrs = ["mldsa44.h"], | ||
| deps = [ | ||
| ":ct", | ||
| ":mldsa_mu", | ||
| "//third_party/embedpqc/ports:shake", | ||
| ], | ||
| ) |
There was a problem hiding this comment.
Are we bringing in both the regular and tiny versions of the functions?
There was a problem hiding this comment.
I don't have the tools for measuring latency on real chips now, maybe we can keep both variants for now and decide later?
There was a problem hiding this comment.
I think it is almost certain we only need tiny, no @cfrantz ?
There was a problem hiding this comment.
Dropped all variants other than mldsa-44-tiny variant for this initial PR.
5ab37dc to
a586c10
Compare
|
Can we add some cycle counts to the tiny executions maybe? |
Using `.strip()` on the file content before splitting removes all leading whitespaces of the entire file. By switching to `.rstrip()`, we preserve any leading empty lines/spaces while still stripping trailing whitespaces and ensuring the file ends with a single newline. Signed-off-by: Yi-Hsuan Deng <yhdeng@google.com> Change-Id: Ib9954c5ed78c1610b1148ee7913f786f6a6a6964
This patch exports the `kmac_squeeze_words` and `kmac_done` functions from the kmac driver to allow caller to squeeze an arbitrary number of words from the Keccak state incrementally. Also, adds `kmac_shake128_configure` to support SHAKE-128 configuration. Signed-off-by: Yi-Hsuan Deng <yhdeng@google.com> Change-Id: Ide996b205dcd4cf41425571315cd0b496a6a6964
60eab91 to
e0d0d6d
Compare
Import `embedpqc` library containing embedded friendly implementations of ML-DSA-44, ML-DSA-65, and ML-DSA-87 signatures derived from BoringSSL. This commit pulls in both the standard variants and the stack usage optimized "tiny" variants of ML-DSA, integrated with OpenTitan's hardware KMAC block for SHAKE acceleration. The change also introduces smoke tests for each variant targeting the Earlgrey chip. Signed-off-by: Yi-Hsuan Deng <yhdeng@google.com> Change-Id: Ide996b205dcd4cf41425571315cd0b496a6a6964
nasahlpa
left a comment
There was a problem hiding this comment.
Thanks @sasdf for pulling this code into the repository.
I've focused my review on the fist two commits as well as the test code in sw/device/tests/embedpqc. This LGTM!
The only remark I have is that we should add a readme to third_party/embedpqc stating that this code is not hardened against SCA and FI attacks.
| print(f'Binary file: "{path}"') | ||
| continue | ||
| new_text = "\n".join([line.rstrip() for line in old_text.strip().split("\n")]) + "\n" | ||
| new_text = "\n".join([line.rstrip() for line in old_text.rstrip().split("\n")]) + "\n" |
There was a problem hiding this comment.
With this change, the documentation at the top of the file is outdated:
# - There is no leading whitespace in the file.
| } | ||
|
|
||
| if (launder32(offset) == kShake256KeccakRateWords) { | ||
| if (launder32(offset) == rate_words) { |
There was a problem hiding this comment.
In cryptolib, we have:
opentitan/sw/device/lib/crypto/drivers/kmac.c
Line 762 in 56715af
So here we are running an additional CMD.RUN after a last full block. This is fine.
| rom_error_t kmac_shake256_squeeze_end(uint32_t *out, size_t outlen); | ||
|
|
||
| /** | ||
| * Squeeze arbitrary number of words from the Keccak state. |
There was a problem hiding this comment.
Is it really an arbitrary number of words or should it be a multiple of rate_words? If a first call would ask for non-rate multiple, the next call to this function would then re-read those words? I think it might be worth documenting this here.
| ":mldsa_testvectors", | ||
| "//sw/device/lib/runtime:log", | ||
| "//sw/device/lib/testing/test_framework:ottf_main", | ||
| "//third_party/embedpqc/ports:mldsa44_tiny_caller", |
There was a problem hiding this comment.
| "//third_party/embedpqc/ports:mldsa44_tiny_caller", | |
| "//third_party/embedpqc/ports:mldsa44_tiny_caller", | |
| "//third_party/embedpqc:mldsa44_tiny", |
I think this could be added to make the includes more robust.
| LOG_INFO("Sign Test Passed."); | ||
|
|
||
| // 3. Verify Test | ||
| mldsa44_tiny_pub_from_seed_with_stack(buf, kMldsa44SignSeed, |
There was a problem hiding this comment.
Should we compare here to a golden public key? On the other hand, if this fails, the verify below would also fail. So fine for me to leave it as it is.
This PR integrates the
embedpqcsoftware implementation of ML-DSA and updates the KMAC driver to support the required SHAKE operations.The embedpqc library from Google's BoringSSL doesn't have public repo yet, so we pull the sources directly for now. This PR only pulls the mldsa-44 tiny-stack profile.
Key Changes
third_party/embedpqc):embedpqclibrary files.third_party/embedpqc/ports/that implements theSHAKE128andSHAKE256interfaces by wrapping the Silicon Creator KMAC driver.sw/device/silicon_creator/lib/drivers/):kmac_shake128_configure()to support SHAKE-128 mode.kmac_squeeze_words()andkmac_done(), allowing arbitrary-length squeezing required by ML-DSA.sw/device/tests/embedpqc/):Stack usage estimation: